implement list_objects-function an test
authorManuel Stühn <freebsd@justmail.de>
Tue, 16 Nov 2021 08:17:02 +0000 (09:17 +0100)
committerColin Walters <walters@verbum.org>
Fri, 6 May 2022 16:53:57 +0000 (12:53 -0400)
rust-bindings/rust/src/repo.rs
rust-bindings/rust/tests/functions/mod.rs

index 827dcb4f4817f792fd9e5ca18800dc1864e8452a..486e087c9bd5aca97ebae2dd06e00f0833c8164e 100644 (file)
@@ -2,6 +2,7 @@
 use crate::RepoListRefsExtFlags;
 use crate::{Checksum, ObjectName, ObjectType, Repo, RepoTransactionStats};
 use ffi;
+use ffi::OstreeRepoListObjectsFlags;
 use glib::ffi as glib_sys;
 use glib::{self, translate::*, Error, IsA};
 use std::{
@@ -23,11 +24,22 @@ unsafe extern "C" fn read_variant_table(
     set.insert(ObjectName::new_from_variant(value));
 }
 
-unsafe fn from_glib_container_variant_set(ptr: *mut glib_sys::GHashTable) -> HashSet<ObjectName> {
+unsafe extern "C" fn read_variant_table_from_key(
+    key: glib_sys::gpointer,
+    _value: glib_sys::gpointer,
+    hash_set: glib_sys::gpointer,
+) {
+    let key: glib::Variant = from_glib_none(key as *const glib_sys::GVariant);
+    let set: &mut HashSet<ObjectName> = &mut *(hash_set as *mut HashSet<ObjectName>);
+    set.insert(ObjectName::new_from_variant(key));
+}
+
+unsafe fn from_glib_container_variant_set(ptr: *mut glib_sys::GHashTable, from_key: bool) -> HashSet<ObjectName> {
     let mut set = HashSet::new();
+    let read_variant_table_cb = if from_key { read_variant_table_from_key } else { read_variant_table };
     glib_sys::g_hash_table_foreach(
         ptr,
-        Some(read_variant_table),
+        Some(read_variant_table_cb),
         &mut set as *mut HashSet<ObjectName> as *mut _,
     );
     glib_sys::g_hash_table_unref(ptr);
@@ -115,7 +127,7 @@ impl Repo {
                 &mut error,
             );
             if error.is_null() {
-                Ok(from_glib_container_variant_set(hashtable))
+                Ok(from_glib_container_variant_set(hashtable, false))
             } else {
                 Err(from_glib_full(error))
             }
@@ -147,6 +159,32 @@ impl Repo {
         }
     }
 
+    /// List all repo objects
+    pub fn list_objects<P: IsA<gio::Cancellable>>(
+        &self,
+        flags: OstreeRepoListObjectsFlags,
+        cancellable: Option<&P>,
+    ) -> Result<HashSet<ObjectName>, Error> {
+        unsafe {
+            let mut error = ptr::null_mut();
+            let mut hashtable = ptr::null_mut();
+
+            ffi::ostree_repo_list_objects(
+                self.to_glib_none().0,
+                flags,
+                &mut hashtable,
+                cancellable.map(AsRef::as_ref).to_glib_none().0,
+                &mut error
+            );
+
+            if error.is_null() {
+                Ok(from_glib_container_variant_set(hashtable, true))
+            } else {
+                Err(from_glib_full(error))
+            }
+        }
+    }
+
     /// List refs with extended options.
     #[cfg(any(feature = "v2016_4", feature = "dox"))]
     pub fn list_refs_ext<P: IsA<gio::Cancellable>>(
index 15908731f1c78e3bfba870f1fbdbcf51fcba7aea..ae5f99f134a05249e7c3372aa209e61625776f93 100644 (file)
@@ -2,6 +2,34 @@ use crate::util::TestRepo;
 use gio::NONE_CANCELLABLE;
 use ostree::{checksum_file_from_input, ObjectType};
 
+#[test]
+fn list_repo_objects() {
+    let repo = TestRepo::new();
+    let commit_checksum = repo.test_commit("test");
+    let mut dirtree_cnt = 0;
+    let mut dirmeta_cnt = 0;
+    let mut file_cnt = 0;
+    let mut commit_cnt = 0;
+
+    let objects = repo.repo.list_objects( ffi::OSTREE_REPO_LIST_OBJECTS_ALL, NONE_CANCELLABLE).expect("List Objects");
+    for object in objects {
+        if object.object_type() == ObjectType::Commit {
+            commit_cnt += 1;
+            assert_eq!(commit_checksum.to_string(), object.checksum());
+        } else if object.object_type() == ObjectType::DirTree {
+            dirtree_cnt += 1;
+        } else if object.object_type() == ObjectType::DirMeta {
+            dirmeta_cnt += 1;
+        } else if object.object_type() == ObjectType::File {
+            file_cnt += 1;
+        } else { panic!("unexpected object type {}", object.object_type()); }
+    }
+    assert_eq!(dirtree_cnt, 2);
+    assert_eq!(dirmeta_cnt, 1);
+    assert_eq!(file_cnt, 1);
+    assert_eq!(commit_cnt, 1);
+}
+
 #[test]
 fn should_checksum_file_from_input() {
     let repo = TestRepo::new();